package com.googlecode.lookie.swing.iconlist;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;

import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;

public class CellRenderer
    implements ListCellRenderer
{

    private static final Insets insets = new Insets( 5, 5, 5, 5 );

    private final IconPanel panel = new IconPanel();

    private final LabelProvider provider;

    @SuppressWarnings("unused")
    private final ListCellRenderer delegate;

    private int iconAreaSize;

    public CellRenderer( LabelProvider provider )
    {
        this( provider, new DefaultListCellRenderer() );
    }

    public CellRenderer( LabelProvider provider, ListCellRenderer delegate )
    {

        this.provider = provider;

        this.delegate = delegate;

        panel.init();
        setIconAreaSize( 300 );
    }

    public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected,
                                                   boolean cellHasFocus )
    {
        Icon icon = provider.getIcon( value, iconAreaSize );
        panel.iconLabel.setIcon( icon );

        panel.textLabel.setText( provider.getText( value ) );
        panel.setToolTipText( provider.getTooltipText( value ) );

        Color fg = isSelected ? list.getSelectionForeground() : list.getForeground();
        Color bg = isSelected ? list.getSelectionBackground() : list.getBackground();
        panel.setForeground( fg );
        panel.setBackground( bg );

        return panel;
    }

    public void setIconAreaSize( int size )
    {
        iconAreaSize = size;

        int width = size + insets.left + insets.right;
        int iconLabelHeight = size + insets.top + insets.bottom;
        int textLabelHeight = 20 + insets.top + insets.bottom;

        panel.iconLabel.setPreferredSize( new Dimension( width, iconLabelHeight ) );
        panel.iconLabel.setMinimumSize( new Dimension( width, iconLabelHeight ) );

        panel.textLabel.setPreferredSize( new Dimension( width, textLabelHeight ) );
    }

    public Dimension getComponentSize()
    {
        return panel.getPreferredSize();
    }

    private class IconPanel
        extends JPanel
    {

        private static final long serialVersionUID = 4625653386648287056L;

        JLabel iconLabel = new JLabel();

        JLabel textLabel = new JLabel();

        public IconPanel()
        {
            super( new GridBagLayout() );
        }

        void init()
        {
            iconLabel.setHorizontalAlignment( SwingConstants.CENTER );
            iconLabel.setVerticalAlignment( SwingConstants.CENTER );

            textLabel.setHorizontalAlignment( SwingConstants.CENTER );
            textLabel.setPreferredSize( new Dimension( 175, 20 ) );

            GridBagConstraints constraints;

            constraints = new GridBagConstraints();
            constraints.gridx = 0;
            constraints.gridy = 0;
            constraints.insets = insets;
            add( iconLabel, constraints );

            constraints = new GridBagConstraints();
            constraints.gridx = 0;
            constraints.gridy = 1;
            constraints.insets = insets;
            add( textLabel, constraints );
        }

        public void repaint( final long tm, final int x, final int y, final int width, final int height )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void repaint( final Rectangle r )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        protected void firePropertyChange( final String propertyName, final Object oldValue, final Object newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final byte oldValue, final byte newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final char oldValue, final char newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final short oldValue, final short newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final int oldValue, final int newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final long oldValue, final long newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final float oldValue, final float newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final double oldValue, final double newValue )
        {
        }

        /**
         * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
         */

        public void firePropertyChange( final String propertyName, final boolean oldValue, final boolean newValue )
        {
        }

    }

}
